/*******************************************************************************
 * Copyright (c) 2009, 2013 EclipseSource and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    EclipseSource - initial API and implementation
 ******************************************************************************/
package it.rap.applications.property.manager.core;

import static it.rap.applications.property.manager.utils.ImageUtil.getImage;
import it.rap.applications.container.IContainerPage;
import it.rap.applications.contributions.manager.services.IDownloadServiceHandler;
import it.rap.applications.contributions.manager.utils.SubMenuAction;
import it.rap.applications.property.manager.services.DownloadServiceHandler;
import it.rap.applications.property.manager.services.ImgDownloadServiceHandler;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.DialogCellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.service.ServiceHandler;
import org.eclipse.rap.rwt.service.ServiceManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Link;


public class CorePage implements IContainerPage {
	
	public static final String PROPERTY_TYPE = "Type";
	public static final String PROPERTY_NAME = "Name";
	public static final String PROPERTY_VALUE = "Value";
	
	public static final String[] PROPS = { PROPERTY_TYPE, PROPERTY_NAME, PROPERTY_VALUE };
	private static final int COMPOSITE_COLUMN = 1;

	private Composite parent = null;;
	private TableViewer tv = null; 
	private Table uiTableProperties;
	
	private List<MyProperty> propertiesList= new ArrayList<MyProperty>();
	private Text text;
	
	private String fileResultName;
	private String[] fileNames; 
	
	private CellEditor[] editors = new CellEditor[3];	
	private Label link;
	
	private List<SubMenuAction> actions = new ArrayList<SubMenuAction>();

	private Composite contentComp;
	

 	/**
	 * @wbp.parser.entryPoint
	 */	
	public void wBuilderEntriPoint(Composite parent){
		 contentComp = new Composite( parent, SWT.NONE);		 
	     this.createControl( contentComp );
	}

  public void createControl(Composite _parent ) {
	    parent = _parent;
	    parent.setLayout(new GridLayout(1, false));
	    
	    createHeader(parent);	  
	    
	    SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
	    sashForm.setLayoutData(new GridData(GridData.FILL, SWT.FILL, true, true ));
	    
	    tv = new TableViewer(sashForm, SWT.BORDER | SWT.FULL_SELECTION);
	    uiTableProperties = tv.getTable();
				
	    for (int i = 0, n = uiTableProperties.getColumnCount(); i < n; i++) {
	      uiTableProperties.getColumn(i).pack();
	    } 
	    
	    tv.setContentProvider(new PropertyContentProvider());
	    tv.setLabelProvider(new PropertyLabelProvider());
	    tv.setInput( propertiesList );
	    Table uiTableProperties = tv.getTable();
	    
	    TableColumn tableColumn_1 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_1.setWidth(70);
	    tableColumn_1.setText( PROPERTY_TYPE );
	    TableColumn tableColumn_2 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_2.setWidth(200);
	    tableColumn_2.setText( PROPERTY_NAME );				
	    TableColumn tableColumn_3 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_3.setWidth(204);
	    tableColumn_3.setText( PROPERTY_VALUE );
	    
	    uiTableProperties.setLinesVisible(true);
	    uiTableProperties.setHeaderVisible(true);
	    
		tv.setColumnProperties(PROPS);
		tv.setCellModifier(new PropertyCellModifier(tv));
		editors[0] = new ComboBoxCellEditor(uiTableProperties, RowType.INSTANCES, SWT.READ_ONLY);
		editors[1] = new TextCellEditor(uiTableProperties);
		editors[2] = new TextCellEditor(uiTableProperties);
		tv.setCellEditors(editors);
		sashForm.setWeights(new int[] {1});
	    		
		text = new Text(sashForm, SWT.BORDER | SWT.V_SCROLL | SWT.MULTI);				
	
		ServiceManager manager = RWT.getServiceManager();
		IDownloadServiceHandler handler = new DownloadServiceHandler();	
		IDownloadServiceHandler imgHandler = new ImgDownloadServiceHandler();	
		
		try{
			manager.registerServiceHandler( DownloadServiceHandler.ID, (ServiceHandler)handler );
			manager.registerServiceHandler( ImgDownloadServiceHandler.ID, (ServiceHandler)imgHandler );
		} catch( IllegalArgumentException e ){
			Logger.getAnonymousLogger().log(Level.SEVERE, e.getMessage());
		}
		
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayout(new GridLayout(1, false));
		composite.setLayoutData( new GridData(SWT.LEFT, SWT.FILL, true, false) );
	  	    
	    link = new Label( composite, SWT.NONE );
	    link.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
	    link.setData( RWT.MARKUP_ENABLED, Boolean.TRUE );
	    link.setData( RWT.CUSTOM_ITEM_HEIGHT, new Integer( 27 ) ); 
		String htmlLink = "<a href='"+ new DownloadServiceHandler().createDownloadUrl( "properties.ini" ) +"'>"
				 		+ "<img src='"+ new ImgDownloadServiceHandler().createDownloadUrl( "down.gif" )  + "' width='16' height='16' /> Download properties file!</a>";
														
		htmlLink = htmlLink.replaceAll( "&", "&#38;");
		link.setText( htmlLink );

	    link.setVisible( false );

	}

	private void createHeader( Composite parent ) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayout(new GridLayout(1, false));
		composite.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false, 0, 0));
	    ToolBar toolBar = new ToolBar(composite,  SWT.NONE  );
	    ToolItem dropDown = new ToolItem(toolBar, SWT.DROP_DOWN);
	    dropDown.setText("Actions");
	    dropDown.setImage( getImage( composite.getDisplay(), "no-flag.png" ) );
	    dropDown.setToolTipText("Select for more actions...");
	    Menu menu = new Menu( dropDown.getParent().getShell(), SWT.POP_UP );
	    dropDown.addListener( SWT.Selection, new DropDownSelectionListener( menu ) );
	    SubMenuItemSelectionListener subMenuListener = new SubMenuItemSelectionListener( dropDown );
		  
		initSubMenuAction();
		for( SubMenuAction action: actions  ){
		    MenuItem item = new MenuItem( menu, SWT.PUSH );
		    item.setText( action.getName() );
		    item.setImage( action.getImage() );
		    item.setData( action );
		    item.addListener( SWT.Selection, subMenuListener );
		}
	}
	private void initSubMenuAction(){
		actions.add(
		new SubMenuAction("New item", getImage( parent.getDisplay(), "add_obj.png" ) ){
				@Override
				public void handleAction() {

			        MyProperty p = new MyProperty();
			        p.setPropertyType( 0 );
			        p.setPropertyName( "Name" );       
			        p.setPropertyValue( "Value" );
			        propertiesList.add(p);
			        tv.refresh();
			      
				}
		    }
		);
		actions.add( 
			new SubMenuAction("Save",  getImage( parent.getDisplay(), "save_obj.png" ) ){
				@Override
				public void handleAction() {

					try {
						if ( propertiesList != null && propertiesList.size() > 0 ){
							text.setText("");
							for(MyProperty p : propertiesList){					
								text.append( p.print() );
								text.append( "\n" );
							}	
							
							File f = new File( "C:\\Temp\\properties.ini" );
							
							FileOutputStream of = new FileOutputStream( f );
							of.write( text.getText().getBytes(), 0, text.getText().getBytes().length);
							of.flush();
							of.close();
							
							link.setVisible( true );
							
						}	
					} catch (FileNotFoundException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}	
				}
		    }		
		);
		actions.add(
			   new SubMenuAction("Load file", getImage( parent.getDisplay(), "file.png" ) ){
					@Override
					public void handleAction() {

						
						 // FileUpload fileUpload = new FileUpload( parent, SWT.MULTI );			 

						  FileDialog fileDialog = new FileDialog( getShell(), SWT.TITLE | SWT.SINGLE );
						  fileDialog.setText( "Upload Property file" );			 
						  fileDialog.open();
						  fileNames = fileDialog.getFileNames();
						  if (  fileNames != null && fileNames.length > 0 && !fileNames[0].equalsIgnoreCase("") ){
							  File f1 = new File( fileNames[0] );
					  		  if(	f1.canRead() ){
					  			  try {
					  				  InputStream is = new FileInputStream( f1 );
					  				  BufferedReader br = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
						    		  String line = "";
									  while ((line  = br.readLine()) != null) {
										  // Deal with the line
										  if ( line.startsWith("#") ){
											  MyProperty p = new MyProperty();
											  p.setPropertyType( 0 );
											  if ( line.substring(1).split("=").length >= 2  ){
												  p.setPropertyName( line.substring(1).split("=")[0] );    
												  p.setPropertyValue( line.substring(1).split("=")[1] );	
											  } else {
												  p.setPropertyName( line.substring(1) );
												  p.setPropertyValue( "");	
											  }
											  propertiesList.add(p);
											  tv.refresh();
										  } else {
											  try {
												  MyProperty p = new MyProperty();
												  p.setPropertyType( 1 );
												  p.setPropertyName( line.split("=")[0] );       
												  p.setPropertyValue( line.split("=")[1] );
												  propertiesList.add(p);
												  tv.refresh();
											  } catch( IndexOutOfBoundsException e2 ){
												  e2.printStackTrace();
											  }
										  }
									  	}	
						    		    // Done with the file    		    	
										br.close();
										br = null;
						    		    is = null;
										
						    		    MessageDialog.openInformation( getShell(), "File Upload", "Upload complete!");
									} catch (IOException e1) {
										// TODO Auto-generated catch block
										e1.printStackTrace();
									}  		    	
					  		    }	
						  }
					}
			    }
		);
	}

	public class SubMenuItemSelectionListener implements Listener {

		private static final long serialVersionUID = -3928858460335365662L;
		private final ToolItem dropDown;

	    public SubMenuItemSelectionListener( ToolItem dropDown ) {
	      this.dropDown = dropDown;
	    }

	    public void handleEvent( Event event ) {
	      MenuItem item = ( MenuItem )event.widget;
	      SubMenuAction action = ( SubMenuAction )item.getData();
	      
	      if ( action.getImage() != null ){
	    	  dropDown.setImage( item.getImage() );
	    	  dropDown.setToolTipText( "Your last action was: " + action.getName() );
	      }
	      dropDown.setData( action );
	      
	      executeAction( action );
	    }

		private void executeAction(SubMenuAction action) {
			action.handleAction();
		}


	}

	public class DropDownSelectionListener implements Listener {

		private static final long serialVersionUID = 3413309950050125164L;
		private final Menu menu;

	    public DropDownSelectionListener( Menu menu ) {
	      this.menu = menu;
	    }

	    public void handleEvent( Event event ) {
	      ToolItem dropDown = ( ToolItem )event.widget;
	      if( event.detail == SWT.ARROW ) {
	        Point point = dropDown.getParent().toDisplay( event.x, event.y );
	        menu.setLocation( point );
	        menu.setVisible( true );
	      } else {
	    	  final SubMenuAction dropDownAction = (SubMenuAction) dropDown.getData();
	    	  if ( dropDownAction == null ) return;
	    	  MessageDialog confirm = new MessageDialog(parent.getShell(), "Recall action?", null, "Recall action "+dropDownAction.getName()+"?", MessageDialog.CONFIRM, new String[]{ "OK", "Annulla" }, 1){
				private static final long serialVersionUID = 4972001426579301330L;
				@Override
	    	      protected int getShellStyle() {
	    	        return super.getShellStyle() | SWT.SHEET;
	    	      }
	    	      @Override
	    	      public boolean close() {
	    	        boolean result = super.close();
	    	        int code = getReturnCode();
	    	        if ( code == 0 ){
	    	        	dropDownAction.handleAction();
	    	        }
	    	        return result;
	    	      }
	    	    };
	    	    confirm.open();
	    	  }
	      }
	    }

	public TableViewer getTv() {
		return tv;
	}
	
	public void setTv(TableViewer tv) {
		this.tv = tv;
	}
	
	public Table getUiTableProperties() {
		return uiTableProperties;
	}
	
	public void setUiTableProperties(Table uiTableProperties) {
		this.uiTableProperties = uiTableProperties;
	}
	
	public List<MyProperty> getPropertiesList() {
		return propertiesList;
	}
	
	public void setPropertiesList(List<MyProperty> propertiesList) {
		this.propertiesList = propertiesList;
	}
	
	public Text getText() {
		return text;
	}
	
	public void setText(Text text) {
		this.text = text;
	}
	
	public String getFileResultName() {
		return fileResultName;
	}
	
	public void setFileResultName(String fileResultName) {
		this.fileResultName = fileResultName;
	}
	
	public String[] getFileNames() {
		return fileNames;
	}
	
	public void setFileNames(String[] fileNames) {
		this.fileNames = fileNames;
	}
	
	private Shell getShell() {
		return Display.getCurrent().getActiveShell();
	}
}


class PropertyContentProvider implements IStructuredContentProvider {
  /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

public Object[] getElements(Object inputElement) {
    return ((List<?>) inputElement).toArray();
  }

  public void dispose() {
  }

  public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
  }
}

class PropertyLabelProvider implements ITableLabelProvider {
	  /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public Image getColumnImage(Object element, int columnIndex) {
	    return null;
	  }

	  public String getColumnText(Object element, int columnIndex) {
	    MyProperty p = (MyProperty) element;
	    switch (columnIndex) {
	    case 0:
	      return RowType.INSTANCES[p.getPropertyType()];
	    case 1:
	      return p.getPropertyName();
	    case 2:
	      return p.getPropertyValue();	   
	    }
	    return null;
	  }
	  public void addListener(ILabelProviderListener listener) {
	  }

	  public void dispose() {
	  }

	  public boolean isLabelProperty(Object element, String property) {
	    return false;
	  }
	  public void removeListener(ILabelProviderListener listener) {
	  }

	}

class MyProperty {
  private Integer propertyType;
  private String propertyName;
  private String propertyValue;
  
	public Integer getPropertyType() {
		return propertyType;
	}
	public String print() {
		StringBuffer buff = new StringBuffer("");
		if ( propertyType == 0 ){
			buff.append("#").append( propertyName );
			if ( propertyValue != null ) buff.append(" ").append( propertyValue );
			return buff.toString();
		} else {
			buff.append( propertyName ).append( "=" ).append( propertyValue );
			return buff.toString();
		}
	}
	public void setPropertyType(Integer propertyType) {
		this.propertyType = propertyType;
	}
	public String getPropertyName() {
		return propertyName;
	}
	public void setPropertyName(String propertyName) {
		this.propertyName = propertyName;
	}
	public String getPropertyValue() {
		return propertyValue;
	}
	public void setPropertyValue(String propertyValue) {
		this.propertyValue = propertyValue;
	}

}


class PropertyCellModifier implements ICellModifier {
	  private Viewer viewer;

	  public PropertyCellModifier(Viewer viewer) {
	    this.viewer = viewer;
	  }

	  public boolean canModify(Object element, String property) {
	    return true;
	  }

	  public Object getValue(Object element, String property) {
	    MyProperty p = (MyProperty) element;
	    if (CorePage.PROPERTY_TYPE.equals(property))
	      return p.getPropertyType();
	    else if (CorePage.PROPERTY_NAME.equals(property))
	      return p.getPropertyName();
	    else if (CorePage.PROPERTY_VALUE.equals(property))
	      return p.getPropertyValue();	   
	    else
	      return null;
	  }

	  public void modify(Object element, String property, Object value) {
	    if (element instanceof Item) element = ((Item) element).getData();

	    MyProperty p = (MyProperty) element;
	    if (CorePage.PROPERTY_TYPE.equals(property))
	      p.setPropertyType( (Integer)value );	   
	    else if (CorePage.PROPERTY_NAME.equals(property))
	      p.setPropertyName((String) value);
	    else if (CorePage.PROPERTY_VALUE.equals(property))
	      p.setPropertyValue((String) value);
	   
	    viewer.refresh();
	  }
	}


class RowType {
	  public static final String COMMENT = "#";
	  public static final String PROPERTY = "P";
	 
	  public static final String[] INSTANCES = { COMMENT, PROPERTY };
	}

class CompareDialogCellEditor extends DialogCellEditor {
    public CompareDialogCellEditor(Composite parent) {
           super(parent);
    }

    @Override
    protected Button createButton(Composite parent) {
           Button button = super.createButton(parent);
           button.setText("...");
           return button;
    }

    @Override
    protected Object openDialogBox(Control cellEditorWindow) {
           MessageDialog.openInformation(cellEditorWindow.getShell(), "Test", "It works");
           return null;
    }    
}